Last updated on May 29, 2023 am
Loading a Binary
angr是通过CLE模块来装载一个二进制文件,也就是说CLE的接口也可以用于angr。
The Loader 目前我们可以用以下几行代码装载一个二进制文件
1 2 3 4 import angr, monkeyhex proj = angr.Project('examples/fauxware/fauxware' ) proj.loader <Loaded fauxware, maps [0x400000 :0x5008000 ]>
Loaded Objects 前面提到Angr使用CLE来装载二进制文件,而CLE装载器即cle.Loader
装载了这个二进制文件的所有objects,并且把他们映射到一个内存地址。每一个不同类型的binary objec都可以由cle.Backend
处理,比如cle.ELF
就是用来装载ELF文件。
loader.all_objects 可以通过loader.all_objects
来获得CLE装载所有objects的列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 >>> proj.loader.all_objects [<ELF Object fauxware, maps [0x400000 :0x60105f ]>, <ELF Object libc-2.23 .so, maps [0x1000000 :0x13c999f ]>, <ELF Object ld-2.23 .so, maps [0x2000000 :0x2227167 ]>, <ELFTLSObject Object cle <ExternObject Object cle <KernelObject Object cle>>> proj.loader.main_object <ELF Object fauxware, maps [0x400000 :0x60105f ]>>>> proj.loader.shared_objects { 'fauxware' : <ELF Object fauxware, maps [0x400000 :0x60105f ]>, 'libc.so.6' : <ELF Object libc-2.23 .so, maps [0x1000000 :0x13c999f ]>, 'ld-linux-x86-64.so.2' : <ELF Object ld-2.23 .so, maps [0x2000000 :0x2227167 ]> }>>> proj.loader.all_elf_objects [<ELF Object fauxware, maps [0x400000 :0x60105f ]>, <ELF Object libc-2.23 .so, maps [0x1000000 :0x13c999f ]>, <ELF Object ld-2.23 .so, maps [0x2000000 :0x2227167 ]>]>>> proj.loader.extern_object <ExternObject Object cle>>> proj.loader.kernel_object <KernelObject Object cle>>> proj.loader.find_object_containing(0x400000 ) <ELF Object fauxware, maps [0x400000 :0x60105f ]>
与object交互 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 obj = proj.loader.main_object obj.entry0x400580 obj.min_addr, obj.max_addr (0x400000 , 0x60105f ) obj.segments <Regions: [<ELFSegment memsize=0xa74 , filesize=0xa74 , vaddr=0x400000 , flags=0x5 , offset=0x0 >, <ELFSegment memsize=0x238 , filesize=0x228 , vaddr=0x600e28 , flags=0x6 , offset=0xe28 >]> obj.sections <Regions: [<Unnamed | offset 0x0 , vaddr 0x0 , size 0x0 >, <.interp | offset 0x238 , vaddr 0x400238 , size 0x1c >, <.note.ABI-tag | offset 0x254 , vaddr 0x400254 , size 0x20 >, ...etc obj.find_segment_containing(obj.entry) <ELFSegment memsize=0xa74 , filesize=0xa74 , vaddr=0x400000 , flags=0x5 , offset=0x0 > obj.find_section_containing(obj.entry) <.text | offset 0x580 , vaddr 0x400580 , size 0x338 > addr = obj.plt['strcmp' ] addr0x400550 obj.reverse_plt[addr]'strcmp' obj.linked_base0x400000 obj.mapped_base0x400000
Symbols and Relocations symbol是可执行文件的重要概念,完成从名字到地址的映射
可以利用loader.find_symbol
寻找特定symbol,它的参数可以是名字,也可以是地址
1 2 3 strcmp = proj.loader.find_symbol('strcmp' ) strcmp <Symbol "strcmp" in libc.so.6 at 0x1089cd0 >
symbol有三种形式地址
.rebased_addr
是全局地址空间的地址
.linked_addr
预链接地址
.relative_addr
即RVA
1 2 3 4 5 6 7 8 9 10 11 12 strcmp.name'strcmp' strcmp.owner <ELF Object libc-2.23 .so, maps [0x1000000 :0x13c999f ]> strcmp.rebased_addr0x1089cd0 strcmp.linked_addr0x89cd0 strcmp.relative_addr0x89cd0
Loading Options 可以给angr.Project传一些参数,以此来约束加载二进制文件的行为
1 2 3 4 5 6 7 1. auto_load_libs 决定是否加载动态链接库,默认开启2. skip_libs 跳过这些依赖库3. ld_path 寻找动态链接库的路径4. backend 后端,比如 blob5. base_addr 基址6. entry_point 入口点7. arch 架构
Symbolic Function Summaries Project会将外部的call转化为自己的符号执行,angr已经把一整套的外部库函数给模拟为SimProcedures了,
可以在angr.SIM_PROCEDURES
字典访问,键值是库的名字,对象是这个库的函数名字
如果没有这个外部函数的SimProcedueres:
auto_load_libs
is True
(default), 执行原来的函数
auto_load_libs
is False
, 也是模拟执行,但返回一个无约束的状态
use_sim_procedures
,这个是angr.Project
的参数,如果是False,只会模拟执行此symbols.默认是True
Hook
proj.hook(addr, hook)
, where hook
is a SimProcedure instance. You can manage your project’s hooks with .is_hooked
, .unhook
, and .hooked_by
, which should hopefully not require explanation.
可以指定length参数,来决定hook后跳多少个bytes指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 stub_func = angr.SIM_PROCEDURES['stubs' ]['ReturnUnconstrained' ] proj.hook(0x10000 , stub_func()) proj.is_hooked(0x10000 ) True proj.hooked_by(0x10000 ) <ReturnUnconstrained> proj.unhook(0x10000 )@proj.hook(0x20000 , length=5 ) def my_hook (state ): state.regs.rax = 1 proj.is_hooked(0x20000 )True
angr这样描述hook
Furthermore, you can use proj.hook_symbol(name, hook)
, providing the name of a symbol as the first argument, to hook the address where the symbol lives. One very important usage of this is to extend the behavior of angr’s built-in library SimProcedures. Since these library functions are just classes, you can subclass them, overriding pieces of their behavior, and then use your subclass in a hook.
也即我们可以用proj.hook_symbol(name,hook)
来替换angr内置的函数,以我们的方式实现